package com.schoolgard.base;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

import org.hibernate.FlushMode;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;

import com.schoolgard.base.query.SearchModel;
import com.supersystem.utils.Page;
import com.supersystem.utils.PageQueryParameter;

/**
 * 所有dao的基类接口
 * 
 * @author luoyg
 * 
 */
public interface BaseDAO<T> {

    // -------------------- 基本检索、增加、修改、删除操作 --------------------
    /**
     * 插入
     * 
     * @param instance
     * @return id
     */
    T create(T instance);

    /**
     * 创建或修改
     * 
     * @param instance
     * @return
     */
    public T createOrModify(T instance);

    /**
     * 删除
     * 
     * @param instance
     */
    void remove(T instance);

    /**
     * 删除
     * 
     * @param list 实体list
     */
    void remove(List<T> list);

    /**
     * 根据hql语句批量删除
     * 
     * @param hql
     */
    public void remove(final String hql);

    /**
     * 修改(默认不进行merge)
     * 
     * @param instance
     */
    void modify(T instance);

    /**
     * 修改
     * 
     * @param instance
     * @param isMerge 是否需要merge
     * @return
     */
    void modify(T instance, boolean isMerge);

    /**
     * 从hibernate 缓存中清楚指定的对象
     * 
     * @param instance
     */
    void clear(T instance);

    /**
     * 
     * @param id
     * @return
     */
    T findById(Serializable id);

    /**
     * 总记录条数
     * 
     * @return
     */
    int getTotalCount();

    /**
     * 根据example查询
     * 
     * @param example
     * @return
     */
    List<T> findByExample(T example);

    // -------------------- HQL检索 --------------------
    /**
     * 根据hql查询
     * 
     * @param hql
     * @return
     */
    List<T> find(String hql);

    /**
     * 根据hql分页查询
     * 
     * @param hql
     * @param firstResult 首行索引
     * @param maxResult 末行索引
     * @return
     */
    List<T> find(final String hql, final int firstResult, final int maxResult);

    /**
     * 根据hql查询
     * 
     * @param hql
     * @param paramater hql中的参数
     * @return
     */
    List<T> find(String hql, Object paramater);

    /**
     * 根据hql分页查询
     * 
     * @param hql
     * @param paramater hql中的参数
     * @param firstResult 首行索引
     * @param maxResult 末行索引
     * @return
     */
    List<T> find(String hql, Object paramater, int firstResult, int maxResult);

    /**
     * 根据hql查询
     * 
     * @param hql
     * @param paramaters hql中的参数组
     * @return
     */
    List<T> find(String hql, Object[] paramaters);

    /**
     * 根据hql分页查询
     * 
     * @param hql
     * @param paramaters hql中的参数组
     * @param firstResult 首行索引
     * @param maxResult 末行索引
     * @return
     */
    List<T> find(final String hql, final Object[] paramaters, final int firstResult, final int maxResult);

    /**
     * hql方式查询，查找所有
     * 
     * @return
     */
    List<T> findAll();

    /**
     * hql方式查询，分页查找所有
     * 
     * @param firstResult 首行索引
     * @param maxResult 末行索引
     * @return
     */
    List<T> findAll(int firstResult, int maxResult);

    /**
     * hql方式查询，根据子句查询 实体别名为instance 主句已经添加形如"FROM Object instance where 1=1 "，需自行构造子句
     * 
     * @param filter 构造子句 ，形如" and instance.id=1"
     * @return
     */
    List<T> query(String filter);

    /**
     * hql方式查询，根据子句分页查询 实体别名为instance 主句已经添加形如"FROM Object instance where 1=1 "，需自行构造子句
     * 
     * @param filter 构造子句 ，形如" and instance.id=1"
     * @param firstResult 首行索引
     * @param maxResult 末行索引
     * @return
     */
    List<T> query(String filter, int firstResult, int maxResult);

    /**
     * hql方式查询，根据子句查询 实体别名为instance 主句已经添加形如"FROM Object instance where 1=1 "，需自行构造子句
     * 
     * @param filter 构造子句,形如" and instance.name like ? and instance.number like ?"
     * @param params 子句中所带参数组
     * @return
     */
    List<T> query(String filter, Object[] params);

    /**
     * hql方式查询，根据子句分页查询 实体别名为instance 主句已经添加形如"FROM Object instance where 1=1 "，需自行构造子句
     * 
     * @param filter 构造子句,形如" and instance.name like ? and instance.number like ?"
     * @param params 子句中所带参数组
     * @param firstResult 首行索引
     * @param maxResult 末行索引
     * @return
     */
    List<T> query(String filter, Object[] params, int firstResult, int maxResult);

    /**
     * hql方式查询，根据属性查询
     * 
     * @param propertyName 属性名称,须同实体的属性名称一致
     * @param value 属性值
     * @return
     */
    List<T> findByProperty(String propertyName, Object value);

    /**
     * hql方式查询，根据属性分页查询
     * 
     * @param propertyName 属性名称,须同实体的属性名称一致
     * @param value 属性值
     * @param firstResult 首行索引
     * @param maxResult 末行索引
     * @return
     */
    List<T> findByProperty(String propertyName, Object value, int firstResult, int maxResult);

    /**
     * hql方式查询，根据属性查询(and查询)
     * 
     * @param propertyNames 属性名称组
     * @param values 属性值组
     * @return
     */
    List<T> findByProperty(String[] propertyNames, Object[] values);

    /**
     * hql方式查询，根据属性分页查询(and查询)
     * 
     * @param propertyNames 属性名称组
     * @param values 属性值组
     * @param firstResult 首行索引
     * @param maxResult 末行索引
     * @return
     */
    List<T> findByProperty(String[] propertyNames, Object[] values, int firstResult, int maxResult);

    /**
     * hql方式查询，根据属性模糊查询
     * 
     * @param propertyName 属性名称
     * @param value 属性值
     * @return
     */
    List<T> fuzzyFindByProperty(String propertyName, Object value);

    /**
     * hql方式查询，根据属性模糊查询(分页查询)
     * 
     * @param propertyName 属性名称
     * @param value 属性值
     * @param firstResult 首行索引
     * @param maxResult 末行索引
     * @return
     */
    List<T> fuzzyFindByProperty(String propertyName, Object value, int firstResult, int maxResult);

    /**
     * hql方式查询，根据多个属性模糊查询(and查询)
     * 
     * @param propertyNames 属性名称组
     * @param values 属性值组
     * @return
     */
    List<T> fuzzyFindByProperty(String[] propertyNames, Object[] values);

    /**
     * hql方式查询，根据多个属性模糊查询(and查询)(分页查询)
     * 
     * @param propertyNames 属性名称组
     * @param values 属性值组
     * @param firstResult 首行索引
     * @param maxResult 末行索引
     * @return
     */
    List<T> fuzzyFindByProperty(String[] propertyNames, Object[] values, int firstResult, int maxResult);

    /**
     * hql方式查询实体并初始化(关联)指定子对象 hql语句所检索的主体的别名为该instance
     * 
     * @param properties 要初始化(关联)的子对象
     * @param alias 指定子对象的别名
     * @param filter 自行构造的hql子句，例如"where ...... order by ......"
     * @return
     * @throws DataBaseAccessException
     */
    public List<T> findJoinProperty(String[] properties, String[] alias, String filter) throws DataBaseAccessException;

    /**
     * hql方式查询实体并初始化(关联)指定子对象 hql语句所检索的主体的别名为该instance
     * 
     * @param properties 要初始化(关联)的子对象
     * @param alias 指定子对象的别名
     * @param filter 自行构造的hql子句，例如"where Member.number=? order by ......"
     * @param filterParams filter子句中的参数组
     * @return
     * @throws DataBaseAccessException
     */
    public List<T> findJoinProperty(String[] properties, String[] alias, String filter, Object[] filterParams)
            throws DataBaseAccessException;

    /**
     * hql方式查询实体并初始化(关联)指定子对象 hql语句所检索的主体的别名为该instance hql中欲初始化的子对象的别名默认与参数properties[i]等值
     * 
     * @param properties 要初始化(关联)的子对象
     * @param filter 自行构造的hql子句，例如"where ...... order by ......"
     * @return
     */
    public List<T> findJoinProperty(String[] properties, String filter);

    /**
     * hql方式查询实体并初始化(关联)指定子对象 hql语句所检索的主体的别名为该instance hql中欲初始化的子对象的别名默认与参数properties[i]等值
     * 
     * @param properties 要初始化(关联)的子对象
     * @param filter 自行构造的hql子句，例如"where Member.number=? order by ......"
     * @param filterParams filter子句中的参数组
     * @return
     */
    public List<T> findJoinProperty(String[] properties, String filter, Object[] filterParams);

    /**
     * hql方式查询实体并初始化(关联)指定子对象 hql语句所检索的主体的别名为该instance
     * 
     * @param properties 要初始化(关联)的子对象
     * @param alias 指定子对象的别名
     * @return
     * @throws DataBaseAccessException
     */
    public List<T> findJoinProperty(String[] properties, String[] alias) throws DataBaseAccessException;

    /**
     * hql方式查询实体并初始化(关联)指定子对象 hql语句所检索的主体的别名为该instance hql中欲初始化的子对象的别名默认与参数properties[i]等值
     * 
     * @param properties 要初始化(关联)的子对象
     * @return
     */
    public List<T> findJoinProperty(String[] properties);

    /**
     * 根据指定属性值查询实体并初始化(关联)指定子对象 (hql查询 eq查询)
     * 
     * @param properties 要初始化(关联)的子对象
     * @param propertyName 查询条件中的属性名称
     * @param eqValue 条件属性的匹配值
     * @return
     */
    public T findJoinPropertyByProperty(String[] properties, String propertyName, Object eqValue);

    // -------------------------------- Criteria 检索 ------------------------------

    /**
     * 根据criteria条件检索
     * 
     * @param criteria 条件
     * @return
     */
    List<T> findByCriteria(DetachedCriteria criteria);

    /**
     * 根据criteria条件进行分页检索
     * 
     * @param criteria 条件
     * @param firstResult 初行
     * @param maxResults 末行
     * @return
     */
    List<T> findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults);

    /**
     * 根据criteria条件查询记录数
     * 
     * @param criteria
     * @return
     */
    int getRowCount(DetachedCriteria criteria);

    /**
     * 根据传入的List<SearchModel>进行QBC查询
     * 
     * @param searchModels 查询实体集
     * @param firstResult 首页
     * @param maxResults 总数
     * @return
     * @throws IllegalArgumentException
     * @throws SecurityException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException
     */
    public List<T> findBySearchModels(List<SearchModel> searchModels, int firstResult, int maxResults)
            throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException,
            NoSuchMethodException;

    /**
     * 根据传入的List<SearchModel>条件查询记录总数
     * 
     * @param searchModels 查询实体集
     * @return
     * @throws IllegalArgumentException
     * @throws SecurityException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException
     */
    public int getRowCountBySearchModels(List<SearchModel> searchModels) throws IllegalArgumentException,
            SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException;

    // -----------------------------------Other -------------------------------
    /**
     * 强制初始化指定属性
     * 
     * @param proxy
     */
    void initialize(Object proxy);

    /**
     * merge
     * 
     * @param object
     */
    Object merge(Object object);

    /**
     * hql方式查询，根据属性查询
     * 
     * @param propertyName 属性名称,须同实体的属性名称一致
     * @param value 属性值
     * @author 朱发强
     * @return T类型对象
     */
    T findOneByProperty(String propertyName, Object value);

    /**
     * hql方式查询，根据多个属性，属性范围查询数据，
     * 
     * @param propertyNames 属性数组
     * @param values1 起始值数组，如果不是范围，则填目标值
     * @param values2 结束值数组，如果不是范围，则传空字符串
     * @param firstResult 开始记录的序列号
     * @param maxResult 需要取得的记录数
     * @return list
     */
    public List<T> findByProperty(String[] propertyNames, Object[] values1, Object[] values2, int firstResult,
                                  int maxResult);

    public List<?> findResults(final String hql, final Object[] paramaters, final int firstResult, final int maxResult);

    public void flush();

    public Page findPage(final DetachedCriteria dc, final PageQueryParameter pageParameter);

    public Page findPage(final String hql, final Object[] parameters, final PageQueryParameter pageParameter);

    public List<?> getResultBySql(String sql);

    public List<T> findBySql(String sql);

    public List<T> findBySql(String sql, final Object[] parameters, int firstIndex, int maxResults);

    public Page findPageBySql(String sql, Object[] parameters, PageQueryParameter pageParameter);

    public int getRowCountBySql(String sql, Object[] parameters);

    public <T1> T1 findById(Class<T1> clazz, Serializable id);

    /**
     * 根据SearchModel分页查询
     * 
     * @param searchModels
     * @param param
     * @return
     */
    public Page findBySearchModels(List<SearchModel> searchModels, PageQueryParameter param)
            throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException,
            NoSuchMethodException;

    Object persist(Object obj);

    void setFlushMode(FlushMode flushMode);

    List<?> findByCriteriaForAnyTypeObject(DetachedCriteria criteria, int firstResult, int maxResults);

    public boolean contains(Object obj);

    public void refresh(Object obj);

    void clear();

    /**
     * 根据searchModels进行查询
     * @param searchModels 查询条件
     * @param param 分页对象
     * @param order 排序条件
     * @return
     * @throws IllegalArgumentException
     * @throws SecurityException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws NoSuchMethodException
     */
    Page findBySearchModels(final List<SearchModel> searchModels, PageQueryParameter param, final Order order)
            throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException,
            NoSuchMethodException;
}
